﻿#include <xy/geom/mesh.h>

#define FAST_OBJ_IMPLEMENTATION
#include <fast_obj/fast_obj.h>

namespace xy
{

namespace geom
{

void mesh::read(std::string path, float scale)
{
    fastObjMesh *objMesh = fast_obj_read(path.c_str());
    if (objMesh == nullptr)
        throw std::runtime_error("Failed to load obj file: " + path);

    // 预先创建顶点，第一个顶点没有用，但是在后面作为点的存在性判断，需要空出来
    vertices.reserve(objMesh->position_count - 1);
    for (unsigned int i = 1; i < objMesh->position_count; i++)
        vertices.emplace_back(objMesh->positions[3 * i + 0] * scale, objMesh->positions[3 * i + 1] * scale,
                              objMesh->positions[3 * i + 2] * scale);
    normals.resize(vertices.size());
    texcoords.resize(vertices.size());

    // 创建面
    for (unsigned int ii = 0; ii < objMesh->group_count; ii++)
    {
        // 获得组
        const fastObjGroup &grp = objMesh->groups[ii];

        int idx = 0;
        for (unsigned int jj = 0; jj < grp.face_count; jj++)
        {
            unsigned int fv = objMesh->face_vertices[grp.face_offset + jj];

            std::vector<int> fvs;
            for (unsigned int kk = 0; kk < fv; kk++)
            {
                fastObjIndex &mi = objMesh->indices[grp.index_offset + idx];

                // 点坐标，根据 if 条件，mi.p > 0，因此第一个点用不上
                if (mi.p)
                {
                    auto vh = vertices[mi.p - 1];
                    fvs.push_back(mi.p - 1);

                    if (mi.t)
                        texcoords[mi.p - 1] = vec2f{objMesh->texcoords[2 * mi.t + 0], objMesh->texcoords[2 * mi.t + 1]};

                    if (mi.n)
                        normals[mi.p - 1] = vec3f{objMesh->normals[3 * mi.n + 0], objMesh->normals[3 * mi.n + 1],
                                                  objMesh->normals[3 * mi.n + 2]};

                    idx++;
                }
            }

            // 创建三角面
            for (auto f : fvs)
                indices.push_back(f);
        }
    }

    fast_obj_destroy(objMesh);
}

} // namespace geom

} // namespace xy
